// src/utils/js_bridge.rs
#![allow(dead_code)]
use serde::{Deserialize, Serialize};
use tauri::{AppHandle, Manager};
use std::{
    sync::{Mutex, Arc},
    collections::HashMap,
    thread,
    sync::atomic::{AtomicU64, Ordering},
};
use log::{error, info};
use tokio::sync::{oneshot, mpsc};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum JsResult {
    Success(String),
    Error(String),
    Timeout,
}

// 消息类型
#[derive(Debug)]
enum JsMessage {
    Eval {
        js_code: String,
        callback: oneshot::Sender<JsResult>,
    },
    // CallFunction {
    //     function_name: String,
    //     args_json: String,
    //     callback: oneshot::Sender<JsResult>,
    // },
}

#[derive(Clone)]
pub struct JsBridge {
    sender: mpsc::Sender<JsMessage>,
    //app_handle: AppHandle,
}

impl JsBridge {
    pub fn new(app_handle: AppHandle) -> Self {
        let (sender, mut receiver) = mpsc::channel(100);
        let app_handle_clone = app_handle.clone();

        // 启动后台线程处理 JS 调用
        thread::spawn(move || {
            // 创建一个新的 Tokio 运行时
            let rt = tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime");

            rt.block_on(async move {
                // 处理消息队列
                while let Some(message) = receiver.recv().await {
                    match message {
                        JsMessage::Eval { js_code, callback } => {
                            let _ = callback.send(execute_js(&app_handle_clone, &js_code).await);
                        }
                        // JsMessage::CallFunction { function_name, args_json, callback } => {
                        //     let js_code = format!("{}({})", function_name, args_json);
                        //     let _ = callback.send(execute_js(&app_handle_clone, &js_code).await);
                        // }
                    }
                }
            });
        });

        Self { sender }//, app_handle
    }

    // 执行任意 JS 代码并异步返回结果
    async fn eval_async(&self, js_code: &str, timeout_ms: u64) -> JsResult {
        let (tx, rx) = oneshot::channel();

        // 发送消息到处理线程
        if let Err(_) = self.sender.send(JsMessage::Eval {
            js_code: js_code.to_string(),
            callback: tx,
        }).await {
            return JsResult::Error("JS bridge channel closed".into());
        }

        // 等待结果
        match tokio::time::timeout(tokio::time::Duration::from_millis(timeout_ms), rx).await {
            Ok(Ok(result)) => result,
            Ok(Err(_)) => JsResult::Error("Callback channel closed unexpectedly".into()),
            Err(_) => JsResult::Timeout,
        }
    }

    // 调用 JS 函数并异步返回结果
    async fn call_js_function_async<T: Serialize>(
        &self,
        function_name: &str,
        args: Option<T>,
        timeout_ms: u64,
    ) -> JsResult {
        let args_json = match args {
            Some(args) => serde_json::to_string(&args).unwrap_or_else(|_| "[]".to_string()),
            None => "[]".to_string(),
        };

        self.eval_async(&format!("{}({})", function_name, args_json), timeout_ms).await
    }
    pub async fn async_script<OUT>(script: &str, timeout: u64) -> Result<OUT, String>
        where
            OUT: serde::de::DeserializeOwned,
    {
        let bridge = get_jsbridge()?;
        let result = bridge.eval_async(script, timeout).await;
        handle_js_result(result)
    }
    pub async fn async_func<IN, OUT>(func_name: &str, args: Option<IN>, timeout: u64) -> Result<OUT, String>
        where
            IN: serde::Serialize,
            OUT: serde::de::DeserializeOwned,
    {
        let bridge = get_jsbridge()?;
        let result = bridge.call_js_function_async(func_name.as_ref(), args, timeout).await;
        handle_js_result(result)
    }

    /// 同步执行 JS 脚本并返回结果
    #[allow(dead_code)]
    pub fn sync_script<OUT>(script: &str, timeout: u64) -> Result<OUT, String>
        where
            OUT: serde::de::DeserializeOwned + Send + 'static,
    {
        // 将引用转换为拥有所有权的 String
        let script_owned = script.to_string();

        TaskManager::global().block_on_future(async move {
            match Self::async_script::<OUT>(&script_owned, timeout).await {
                Ok(result) => Ok(result),
                Err(e) => {
                    error!("执行 JS 脚本失败: {}", e);
                    Err(e)
                }
            }
        })
            .ok_or_else(|| "任务执行失败或被取消".to_string())?
    }

    /// 同步调用 JS 函数并返回结果
    pub fn sync_func<IN, OUT>(func_name: &str, args: Option<IN>, timeout: u64) -> Result<OUT, String>
        where
            IN: serde::Serialize + Send + 'static,
            OUT: serde::de::DeserializeOwned + Send + 'static,
    {
        // 将引用转换为拥有所有权的 String
        let func_name_owned = func_name.to_string();

        TaskManager::global().block_on_future(async move {
            match Self::async_func::<IN, OUT>(&func_name_owned, args, timeout).await {
                Ok(result) => Ok(result),
                Err(e) => {
                    error!("调用 JS 函数失败: {}", e);
                    Err(e)
                }
            }
        })
            .ok_or_else(|| "任务执行失败或被取消".to_string())?
    }
}

// 执行 JS 代码的辅助函数
async fn execute_js(app_handle: &AppHandle, js_code: &str) -> JsResult {
    static NEXT_CALLBACK_ID: AtomicU64 = AtomicU64::new(0);
    let callback_id = NEXT_CALLBACK_ID.fetch_add(1, Ordering::SeqCst);
    let callback_id_str = format!("callback_{}", callback_id);
    let callbacks = get_callbacks();
    //println!("准备执行 JS: {}", js_code);

    // 创建通道接收结果
    let (tx, rx) = oneshot::channel();

    // 注册回调
    {
        let mut callbacks = callbacks.lock().unwrap();
        callbacks.insert(callback_id_str.clone(), tx);
        //println!("已注册回调: {}", callback_id_str);
    }

    // console.log('JS 执行成功, 结果:', result);
    // 包装 JS 代码
    let wrapped_code = format!(
        r#"
        (async () => {{
            try {{
                const result = await ({js_code});
                window.js_bridge_callback({{
                    callback_id: "{callback_id_str}",
                    result: JSON.stringify(result)
                }})
            }} catch (error) {{
                console.error('JS 执行错误:', error);
                window.js_bridge_callback({{
                    callback_id: "{callback_id_str}",
                    error: error.message || String(error)
                }})
            }}
        }})()
        "#
    );

    // 执行 JS
    if let Some(window) = app_handle.get_webview_window("main") {
        //println!("尝试在主窗口执行 JS 代码");
        if let Err(e) = window.eval(&wrapped_code) {
            //println!("JS 执行失败: {}", e);
            // 移除回调
            let mut callbacks = callbacks.lock().unwrap();
            callbacks.remove(&callback_id_str);
            return JsResult::Error(format!("JS execution failed: {}", e));
        }
        //println!("JS 代码已发送执行, 等待回调...");
    } else {
        //println!("主窗口未找到");
        // 移除回调
        let mut callbacks = callbacks.lock().unwrap();
        callbacks.remove(&callback_id_str);
        return JsResult::Error("Main window not found".into());
    }

    // 等待结果
    match rx.await {
        Ok(result) => {
            //println!("收到回调结果");
            result
        }
        Err(_e) => {
            //println!("回调通道错误: {}", e);
            JsResult::Error("Callback channel closed unexpectedly".into())
        }
    }
}

// 全局单例实现
use once_cell::sync::Lazy;
use crate::utils::TaskManager;

static JS_BRIDGE: Lazy<Mutex<Option<JsBridge>>> =
    Lazy::new(|| Mutex::new(None));

// 全局回调映射
static CALLBACKS: Lazy<Arc<Mutex<HashMap<String, oneshot::Sender<JsResult>>>>> =
    Lazy::new(|| Arc::new(Mutex::new(HashMap::new())));

pub fn init_js_bridge(app_handle: AppHandle) {
    let mut bridge = JS_BRIDGE.lock().unwrap();
    *bridge = Some(JsBridge::new(app_handle));
    info!("JS bridge initialized")
}

pub fn get_js_bridge() -> Option<JsBridge> {
    let bridge = JS_BRIDGE.lock().unwrap();
    bridge.clone()
}

pub fn get_callbacks() -> Arc<Mutex<HashMap<String, oneshot::Sender<JsResult>>>> {
    CALLBACKS.clone()
}

fn get_jsbridge() -> Result<JsBridge, String> {
    get_js_bridge().ok_or_else(|| "JS bridge not initialized".to_string())
}

fn handle_js_result<OUT>(result: JsResult) -> Result<OUT, String>
    where
        OUT: serde::de::DeserializeOwned,
{
    match result {
        JsResult::Success(json) => serde_json::from_str(&json)
            .map_err(|e| format!("JSON 解析失败: {}", e)),
        JsResult::Error(e) => Err(e),
        JsResult::Timeout => Err("调用超时".to_string()),
    }
}
